package com.scrcu.idea.ormns.ui;

import cn.hutool.core.util.ObjectUtil;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogBuilder;
import com.intellij.openapi.ui.Messages;
import com.intellij.webSymbols.utils.NameCaseUtils;
import com.scrcu.idea.ormns.common.DBHelper;
import com.scrcu.idea.ormns.common.JavaType;
import com.scrcu.idea.ormns.model.po.Table;
import com.scrcu.idea.ormns.model.vo.CodeGenContextVO;
import com.scrcu.idea.ormns.service.GeneratorService;
import com.scrcu.idea.ormns.service.impl.GeneratorServiceImpl;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class ORMSettingsUI {
    private JPanel main;
    private JButton previousBt;
    private JButton nextBt;
    private JPanel buttonPanel;
    private JPanel settingPanel;
    private JPanel buttonArea;
    private JTabbedPane multiTable;
    private JPanel basicSetting;
    private JTextField packagePath;
    private JTextField moduleName;
    private JTextField authorName;
    private JTextField dataBaseUrl;
    private JTextField portValue;
    private JTextField useName;
    private JTextField passWord;
    private JPanel dataBaseSetting;
    private JTextField dataBaseName;
    private JTextField tablePrefix;
    private JTextField fieldPrefix;
    private JPanel tableSetting;
    private JPanel fieldSetting;
    private JPanel contentPanel;
    private JButton testButton;
    private JTable jTable;
    private JScrollPane jScrollPane;
    private JTabbedPane multiFiledTable;
    private JButton generateButton;
    private JTextField projName;

    private Set<String> tableNames = new HashSet<>();

    private String errorMsg;

    private final GeneratorService generatorService = new GeneratorServiceImpl();

    public ORMSettingsUI(Project project, DialogBuilder builder) {

        this.main.setPreferredSize(new Dimension(1000, 400));

        this.packagePath.setText("com.ist");
        this.projName.setText("ccps");
        this.moduleName.setText("");
        this.authorName.setText("Liu XiaoJun");

//        this.dataBaseUrl.setText("127.0.0.1");
//        this.useName.setText("root");
//        this.passWord.setText("root");

        this.dataBaseUrl.setText("obv4-gz-dev.biz.dev.scrcu.com.cn");
        this.useName.setText("root@scadt#gz_dev_ob42");
        this.passWord.setText("Root@@NX123");

        this.portValue.setText("3306");
        this.dataBaseName.setText("scadt");
        this.jScrollPane.setBorder(null);

        //初始化按钮可见状态
        this.previousBt.setVisible(false);
        this.nextBt.setVisible(true);
        this.generateButton.setVisible(false);
        this.testButton.setVisible(false);

        // 上一页
        this.previousBt.addActionListener(e -> {
            multiTable.setSelectedIndex(multiTable.getSelectedIndex() - 1);
            if(0 <= multiTable.getSelectedIndex() && multiTable.getSelectedIndex() < (multiTable.getTabCount()-1)){
                this.previousBt.setVisible(true);
                this.nextBt.setVisible(true);
                this.nextBt.setEnabled(true);
                if(multiTable.getSelectedIndex() == 0) {
                    this.previousBt.setVisible(false);
                    this.generateButton.setVisible(false);
                    this.testButton.setVisible(false);
                }else if(multiTable.getSelectedIndex() == 1){
                    this.generateButton.setVisible(false);
                    this.testButton.setVisible(true);
                    tableNames = new HashSet<>();
                }else if(multiTable.getSelectedIndex() == 2){
                    this.generateButton.setVisible(false);
                    this.testButton.setVisible(false);
                    multiFiledTable.removeAll();
                }
            }
        });

        // 下一页
        this.nextBt.addActionListener(e -> {
            this.previousBt.setVisible(true);
            //前置检查
            if(multiTable.getSelectedIndex() == 0){
                errorMsg = checkBasicConfig();
                if(ObjectUtil.isNotEmpty(errorMsg)){
                    Messages.showMessageDialog(project, errorMsg, "基础设置检查", Messages.getErrorIcon());
                    return;
                }
            }
            if(multiTable.getSelectedIndex() == 1){
                errorMsg = checkDataBaseConfig();
                if(ObjectUtil.isNotEmpty(errorMsg)){
                    Messages.showMessageDialog(project, errorMsg, "数据库设置检查", Messages.getErrorIcon());
                }else{
                    try {
                        buildTableList();
                    } catch (Exception exception) {
                        Messages.showMessageDialog(project, exception.getMessage(), "数据库连接错误", Messages.getErrorIcon());
                        return;
                    }
                }
            }
            if(multiTable.getSelectedIndex() == 2){
                this.nextBt.setEnabled(false);
                if(tableNames.isEmpty()){
                    Messages.showMessageDialog(project, "ERROR:未选择生产代码的数据库表", "表设置检查", Messages.getErrorIcon());
                    return;
                }else{
                    for(String tableName : tableNames){
                        try {
                            buildFiledList(tableName);
                        } catch (Exception exception) {
                            Messages.showMessageDialog(project, exception.getMessage(), "数据库连接错误", Messages.getErrorIcon());
                            return;
                        }
                    }
                }
            }
            //按钮可见状态
            multiTable.setSelectedIndex(multiTable.getSelectedIndex() + 1);
            this.testButton.setVisible(false);
            if(0 < multiTable.getSelectedIndex() && multiTable.getSelectedIndex() < (multiTable.getTabCount()-1)){
                this.previousBt.setEnabled(true);
                if(multiTable.getSelectedIndex() == 1){
                    this.testButton.setVisible(true);
                }
                if(multiTable.getSelectedIndex() == 2) {
                    nextBt.setEnabled(false);
                }
            }
            if(multiTable.getSelectedIndex() == (multiTable.getTabCount()-1)){
                this.previousBt.setVisible(true);
                this.nextBt.setVisible(false);
                this.generateButton.setVisible(true);
            }
        });

        // 测试数据库链接
        this.testButton.addActionListener(e -> {
            errorMsg = checkDataBaseConfig();
            if(ObjectUtil.isNotEmpty(errorMsg)){
                Messages.showMessageDialog(project, errorMsg, "数据库设置检查", Messages.getErrorIcon());
            }else{
                try {
                    DBHelper dbHelper = new DBHelper(this.dataBaseUrl.getText(), Integer.parseInt(this.portValue.getText()),
                            this.useName.getText(), this.passWord.getText(), this.dataBaseName.getText());
                    String mysqlVersion = dbHelper.testDatabase();
                    Messages.showInfoMessage(project, "Connection successful! \r\nMySQL version : " + mysqlVersion, "OK");
                } catch (Exception exception) {
                    Messages.showMessageDialog(project, exception.getMessage(), "数据库设置检查", Messages.getErrorIcon());
                }
            }
        });
        this.generateButton.addActionListener(e -> {
            // 链接DB

            DBHelper dbHelper = new DBHelper(this.dataBaseUrl.getText(), Integer.parseInt(this.portValue.getText()),
                    this.useName.getText(), this.passWord.getText(), this.dataBaseName.getText());

            // 组装代码生产上下文
            CodeGenContextVO codeGenContextVO = new CodeGenContextVO();
            codeGenContextVO.setModelPackage(this.packagePath.getText() + ".dto." + this.moduleName.getText() +".");
            codeGenContextVO.setServicePackage(this.packagePath.getText() + ".service." + this.moduleName.getText() +".");
            codeGenContextVO.setMapperPackage(this.packagePath.getText() + ".mapper." + this.moduleName.getText() +".");
            codeGenContextVO.setControllerPackage(this.packagePath.getText() + ".web." + this.moduleName.getText() +".");
            codeGenContextVO.setModuleName(this.moduleName.getText());
            codeGenContextVO.setProjectName(this.projName.getText());
            codeGenContextVO.setAuthor(this.authorName.getText());
            List<Table> tables = new ArrayList<>();
            for (String tableName : tableNames) {
                tables.add(dbHelper.getTable(tableName));
            }
            codeGenContextVO.setTables(tables);

            Application applicationManager = ApplicationManager.getApplication();
            applicationManager.runWriteAction(()-> generatorService.generation(project, codeGenContextVO));
            applicationManager.exit();

            builder.getDialogWrapper().close(0);
        });

        // 给表添加事件
        this.jTable.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (1 == e.getClickCount()) {
                    int rowIdx = jTable.rowAtPoint(e.getPoint());
                    Boolean flag = (Boolean) jTable.getValueAt(rowIdx, 0);
                    if (null != flag && flag) {
                        tableNames.add(jTable.getValueAt(rowIdx, 1).toString());
                    } else {
                        tableNames.remove(jTable.getValueAt(rowIdx, 1).toString());
                    }
                }
                if(!tableNames.isEmpty()){
                    nextBt.setEnabled(true);
                }
            }
        });

    }

    /**
     * 构建表信息列表
     */
    private void buildTableList(){
        DBHelper dbHelper = new DBHelper(this.dataBaseUrl.getText(), Integer.parseInt(this.portValue.getText()),
                this.useName.getText(), this.passWord.getText(), this.dataBaseName.getText());
        List<Table> tableList = dbHelper.getAllTableInfo(this.dataBaseName.getText());

        String[] title = {"是否生成", "表名", "业务名", "备注"};
        String tableName = "";
        Object[][] data = new Object[tableList.size()][4];
        for (int i = 0; i < tableList.size(); i++) {
            tableName = tableList.get(i).getName();
            data[i][1] = tableName;
            data[i][2] = getClassName(tableName);
            data[i][3] = tableList.get(i).getComment();
        }

        DefaultTableModel model = new DefaultTableModel(data, title){
            @Override
            public boolean isCellEditable(int row, int column) {
                return column == 0 || column == 2;
            }
        };

        jTable.setModel(model);
        TableColumn tc = jTable.getColumnModel().getColumn(0);
        tc.setCellEditor(new DefaultCellEditor(new JCheckBox()));
        tc.setCellEditor(jTable.getDefaultEditor(Boolean.class));
        tc.setCellRenderer(jTable.getDefaultRenderer(Boolean.class));
        tc.setMaxWidth(100);

        TableColumn tc2 = jTable.getColumnModel().getColumn(2);
        tc2.setCellEditor(new DefaultCellEditor(new JTextField()));
        tc2.setCellEditor(jTable.getDefaultEditor(String.class));
        tc2.setCellRenderer(jTable.getDefaultRenderer(String.class));
    }

    /**
     * 构建字段列表
     * @param tableName 表名
     */
    private void buildFiledList(String tableName){
        DBHelper dbHelper = new DBHelper(this.dataBaseUrl.getText(), Integer.parseInt(this.portValue.getText()),
                this.useName.getText(), this.passWord.getText(), this.dataBaseName.getText());
        Table table = dbHelper.getTable(tableName);

        String[] title = {"字段名", "数据类型", "Java类型", "主键", "是否为空", "属性名", "备注"};
        String fieldName;
        Object[][] data = new Object[table.getColumns().size()][7];
        for (int i = 0; i < table.getColumns().size(); i++) {
            fieldName = table.getColumns().get(i).getName();
            data[i][0] = fieldName;
            data[i][1] = table.getColumns().get(i).getDataType();
            data[i][2] = JavaType.convertType(table.getColumns().get(i).getType()).getSimpleName();
            data[i][3] = table.getColumns().get(i).isId()?"是":"否";
            data[i][4] = "NO".equals(table.getColumns().get(i).getIsNullLable())?"否":"是";
            data[i][5] = getBusinessFieldName(fieldName);
            data[i][6] = table.getColumns().get(i).getComment();
        }

        DefaultTableModel model = new DefaultTableModel(data, title);
        multiFiledTable.addTab(tableName,new JScrollPane(new JTable(model)));
    }

    /**
     * 获取业务名称
     * @param tableName 表名称
     * @return 业务名称
     */
    private String getClassName(String tableName){
        String tablePrefix = this.tablePrefix.getText();
        if(ObjectUtil.isNotEmpty(tablePrefix)){
            if(tableName.startsWith(tablePrefix)){
                tableName = tableName.substring(tablePrefix.length());
            }
        }
        String className = NameCaseUtils.toCamelCase(tableName);
        className = Character.toUpperCase(className.charAt(0)) + className.substring(1);
        return className;
    }

    /**
     * 获取业务字段名称
     * @param fieldName 字段名称
     * @return 业务字段名称
     */
    private String getBusinessFieldName(String fieldName){
        String fieldPrefixStr = this.fieldPrefix.getText();
        if(ObjectUtil.isNotEmpty(fieldPrefixStr)){
            if(fieldName.startsWith(fieldPrefixStr)){
                fieldName = fieldName.substring(fieldPrefixStr.length());
            }
        }
        String businessFieldName = NameCaseUtils.toCamelCase(fieldName);
        businessFieldName = Character.toUpperCase(businessFieldName.charAt(0)) + businessFieldName.substring(1);
        return businessFieldName;
    }


    /**
     * 检查基础设置
     */
    public String checkBasicConfig(){
        if(ObjectUtil.isEmpty(this.packagePath.getText())){
            return "包路径不能为空!";
        }
        if(ObjectUtil.isEmpty(this.projName.getText())){
            return "项目名称不能为空!";
        }
        if(ObjectUtil.isEmpty(this.moduleName.getText())){
            return "模块名不能为空!";
        }
        if(ObjectUtil.isEmpty(this.authorName.getText())){
            return "作者不能为空!";
        }
        return null;
    }

    /**
     * 检查数据库设置
     */
    public String checkDataBaseConfig(){
        if(ObjectUtil.isEmpty(this.dataBaseUrl.getText())){
            return "数据库地址不能为空!";
        }
        if(ObjectUtil.isEmpty(this.portValue.getText())){
            return "数据库端口不能为空!";
        }
        if(ObjectUtil.isEmpty(this.useName.getText())){
            return "数据库用户名不能为空!";
        }
        if(ObjectUtil.isEmpty(this.passWord.getText())){
            return "数据库密码不能为空!";
        }
        if(ObjectUtil.isEmpty(this.dataBaseName.getText())){
            return "数据库名称不能为空!";
        }
        return null;
    }

    public JPanel getMainPanel() {
        return main;
    }

}
